/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ongd.web;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import ongd.negocio.gestion.Apadrinado;
import ongd.negocio.gestion.ControladorApadrinamiento;
import ongd.negocio.gestion.ControladorPadrino;
import ongd.negocio.gestion.ControladorSocio;
import ongd.negocio.gestion.Fraccionado;
import ongd.negocio.gestion.Persona;
import ongd.negocio.gestion.Proyecto;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Elena
 */
@ManagedBean
@ViewScoped
public class Insertar_Persona extends ABean {

    /**
     * Objeto del tipo controladorSocio que nos servirá para crear las
     * instancias correspondientes a la inserción de un socio.
     */
    private ControladorSocio contSocio;
    /**
     * Objeto del tipo controladorApadrinamiento que nos servirá para crear las
     * instancias correspondientes a la inserción de un padrino.
     */
    private ControladorPadrino contPadrino;
    
    /**
     * Objeto del tipo controladorApadrinamiento que nos servirá para crear las
     * instancias correspondientes a la asignación de un proyecto a un padrino.
     */
    private ControladorApadrinamiento contApadrinamiento;    
    /**
     * Objeto del tipo persona que va a contener los datos del nuevo socio
     * o padrino.
     */
    private Persona persona;
    /**
     * Objeto de tipo List que contendrá una lista con el tipo del pago
     * seleccionado por el usuario.
     */
    private List<Fraccionado> tipoPago;
    /**
     * Objeto de tipo String que corresponderá con el nombre del proyecto que 
     * asociaremos a un padrino
     */
    private String proyectoNombre;
    /**
     * Objeto de tipo List que contendra una lista con los apadrinados 
     * disponibles de un determinado proyecto.
     */
    private List<Apadrinado> listaA;
    /**
     * Objeto de tipo apadrinado que corresponderá con el apadrinado
     * asociado a un padrino.
     */
    private Apadrinado apadrinado;
    /**
     * Objeto de tipo proyecto que corresponderá con el proyecto al que va a
     * estar asociado el padrino.
     */
    private Proyecto proyecto;
    /**
     * Objeto de tipo Fraccionado.
     */
    private Fraccionado fmes;

    /**
     * Constructor de la clase.
     */
    public Insertar_Persona() {
        persona = new Persona();
        tipoPago = new ArrayList<Fraccionado>();
        fmes = new Fraccionado();
        listaA = new ArrayList<Apadrinado>();
    }

    /**
     * Método que servirá para cargar los parámetros iniciales en función de
     * la variable pasada al cargar la página.
     */
    @Override
    public void cargaInicial() {
        if (!FacesContext.getCurrentInstance().isPostback()) {
            SesionBean sesion = getSesionBean();
            //lo que se quiera hacer sólo cuando cargue inicialmente la página.
            //Si voy a crear un socio, me creare el controlador de socio apropiado para ello.
            if (sesion.getStrVariable().compareTo("socio") == 0) {
                contSocio = sesion.getControladorSocio();
                persona.setTipo("S");
            } else if (sesion.getStrVariable().compareTo("padrino") == 0) {
                contPadrino = sesion.getControladorPadrino();
                contApadrinamiento = sesion.getControladorApadrinamiento();
                persona.setTipo("P");
            }
        }
        //lo que se quiera hacer siempre que se pulsa un botón o hay una llamada java desde el xhtml
    }

    /**
     * Método que se encargará de llamar a los método adecuados para crear
     * el socio o el padrino respectivamente.
     * @return null
     */
    public String guardarSocio() {
        RequestContext requestContext = RequestContext.getCurrentInstance();
        try {
            if (!tipoPago.isEmpty()) {
                //Si voy a crear un socio.
                if (contSocio != null) {
                    contSocio.crearPersona(persona, tipoPago, null, null);
                    requestContext.addCallbackParam("socioOK", true);
                    //Instancio de nuevo los atributos para poder empezar de cero.
                    persona = new Persona();
                    persona.setTipo("S");
                    tipoPago = new ArrayList<Fraccionado>();
                } else if (contPadrino != null && contApadrinamiento != null) {
                    //Crearé el padrino
                    requestContext.addCallbackParam("padrinoProyecto", true);
                }
            } else {
                requestContext.addCallbackParam("tipoPagoERR", true);
            }
        } catch (PreexistingEntityException ex) {
            Logger.getLogger(Insertar_Persona.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(Insertar_Persona.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     * Método que se encargará asignar un proyecto a un nuevo padrino.
     * @return null
     */
    public String asignarProyecto() {
        RequestContext requestContext = RequestContext.getCurrentInstance();
        if (contApadrinamiento != null) {            
            proyecto = contApadrinamiento.buscarProyecto(proyectoNombre);
            proyectoNombre = new String();
            if (proyecto.esProyectoApadrinamientoGeneral()) {
                guardarPadrino();
            } else if (proyecto.esProyectoApadrinamientoPersonal()) {
                listaA = contApadrinamiento.obtenerApadrinadosDisponibles(proyecto);
                requestContext.addCallbackParam("ap", true);
            }
        }
        return null;
    }

    /**
     * Método que se encargará de llamar a los métodos adecuados para guardar
     * un nuevo padrino
     * @return null
     */
    public String guardarPadrino() {
        if (contPadrino != null) {
            RequestContext requestContext = RequestContext.getCurrentInstance();
            try {
                if (proyecto.esProyectoApadrinamientoPersonal()) {
                    if (apadrinado == null) {
                        requestContext.addCallbackParam("errorap", true);
                    } else {
                        //Crear padrino
                        contPadrino.crearPersona(persona, tipoPago, proyecto, apadrinado);
                        requestContext.addCallbackParam("apOK", true);
                        apadrinado = new Apadrinado();
                    }
                } else if (proyecto.esProyectoApadrinamientoGeneral()) {                    
                    contPadrino.crearPersona(persona, tipoPago, proyecto, null);
                    requestContext.addCallbackParam("apOK1", true);
                }
                persona = new Persona();
                persona.setTipo("P");
                tipoPago = new ArrayList<Fraccionado>();
                proyecto = new Proyecto();
            } catch (PreexistingEntityException ex) {
                Logger.getLogger(Insertar_Persona.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(Insertar_Persona.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }

    /**
     * Método que se encargará de guardar en la lista el fraccionado
     * seleccionado por el usuario.
     * @return null
     */
    public String configurarTipoPago() {
        boolean repetido = false;
        for (Fraccionado f : tipoPago) {
            if (f.getMes().compareTo(fmes.getMes()) == 0) {
                repetido = true;
            }
        }
        //Si no hay meses repetidos guardamos la fraccion en la lista
        if (!repetido) {
            tipoPago.add(fmes);
        }
        fmes = new Fraccionado();
        return null;
    }

    /**
     * Método que devuelve una lista de String con el nombre de cada proyecto
     * de tipo apadrinamiento general o personal que existe en la base de datos.
     * @return availableP
     */
    public List<String> getAvailableP() {
        if (contApadrinamiento != null) {
            List<String> availableP = new ArrayList<String>();
            for (Proyecto p : contApadrinamiento.obtenerProyectosApadrinamiento()) {
                String cadena = p.getNombre();
                availableP.add(cadena);
            }
            return availableP;
        }
        return null;
    }

    /**
     * Método que obtiene el tipoPago.
     * @return lista con el tipo de pago
     */
    public List<Fraccionado> getTipoPago() {
        return tipoPago;
    }

    /**
     * Método que establece el tipo de pago.
     * @param tipoPago
     */
    public void setTipoPago(List<Fraccionado> tipoPago) {
        this.tipoPago = tipoPago;
    }

    /**
     * Método que devuelve un objeto de tipo fraccionado.
     * @return fmes
     */
    public Fraccionado getFmes() {
        return fmes;
    }

    /**
     * Método que establece un objeto de tipo fraccionado.
     * @param fmes
     */
    public void setFmes(Fraccionado fmes) {
        this.fmes = fmes;
    }

    /**
     * Método que devuelve un objeto de tipo persona.
     * @return Persona
     */
    public Persona getPersona() {
        return persona;
    }

    /**
     * Método que establece un objeto de tipo persona.
     * @param persona
     */
    public void setPersona(Persona persona) {
        this.persona = persona;
    }

    
    /**
     * Método que devuelve el nombre del proyecto.
     * @return proyectoNombre
     */
    public String getProyectoNombre() {
        return proyectoNombre;
    }

    /**
     * Método que establece el nombre de un proyecto.
     * @param proyectoNombre 
     */
    public void setProyectoNombre(String proyectoNombre) {
        this.proyectoNombre = proyectoNombre;
    }

    /**
     * Método que obtiene una lista de apadrinados.
     * @return listaA
     */
    public List<Apadrinado> getListaA() {
        return listaA;
    }

    /**
     * Método que establece una lista de apadrinados.
     * @param listaA 
     */
    public void setListaA(List<Apadrinado> listaA) {
        this.listaA = listaA;
    }

    /**
     * Método que obtiene un objeto de tipo apadrinado.
     * @return apadrinado
     */
    public Apadrinado getApadrinado() {
        return apadrinado;
    }

    /**
     * Método que establece un objeto de tipo apadrinado
     * @param apadrinado 
     */
    public void setApadrinado(Apadrinado apadrinado) {
        this.apadrinado = apadrinado;
    }
}